<!DOCTYPE html>
<html>
<head lang="en">
  <meta charset="UTF-8">
  <meta content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0" name="viewport">
  <title>LOW POLY（图片三角化）</title>
  <style>
    #upload {
      display: block;
      margin: 10px 0;
      height: 60px;
      text-align: center;
      line-height: 60px;
      border: 1px solid;
      border-radius: 5px;
      cursor: pointer;
    }

    .touch {
      background-color: #ddd;
    }

    #files {
      display: none
    }

    #box {
      position: relative;
    }

    canvas {
      max-width: 100%;
      margin: 10px auto;
      display: block;
    }

    .loading {
      position: absolute;
      display: none;
      width: 100%;
      height: 40px;
      line-height: 50px;
      text-align: center;
      top: 0;
      bottom: 0;
      margin: auto;
      font-size: 50px;
      color: #FFF;
    }

    .showloading .loading {
      display: block;
    }
  </style>
</head>
<body>
<div>
  <a id="upload">上传图片</a>
  <input type="file" id="files" accept="image/*"/>
</div>

<div id="box">
  <canvas id="cas"></canvas>
  <div class="loading">解析ing...</div>
</div>

<script src="sobel.js"></script>
<script src="delaunay.js"></script>
<script>
  "use strict";
  var inputFile = document.getElementById("files");
  var canvas = document.getElementById("cas");
  var ctx = canvas.getContext("2d");

  var box = document.getElementById("box");
  var uplbtn = document.getElementById("upload");
  uplbtn.onclick = function() {inputFile.click();};
  uplbtn.ontouchstart = function() {this.className = "touch"};
  uplbtn.ontouchend = function() {this.className = ""};

  var jxdvalue = 50;      //精细度，值越小，图片越精细

  var img = new Image();
  img.src = "./test2.jpg";
  img.onload = function() {
    parse(this);
  };

  inputFile.onchange = function() {
    if (!this.files.length) return;

    var file = this.files[0];

    if (!/\/(?:jpeg|png)/i.test(file.type)) {
      alert("图片需为JPG或者PNG格式");
      return;
    }

    var reader = new FileReader();
    reader.onload = function() {
      img = new Image();
      img.src = this.result;

      img.onload = function() {
        parse(this);
      }
    };
    reader.readAsDataURL(file);
  };

  function parse(img) {
    var particles = [];
    canvas.width = (img.width > 800) ? 800 : img.width;
    canvas.height = img.height * canvas.width / img.width;

    ctx.drawImage(img, 0, 0, canvas.width, canvas.height);

    box.className = "showloading";

    setTimeout(function() {
      var imgData = ctx.getImageData(0, 0, canvas.width, canvas.height);

//          收集色值大于40的边缘像素点
      var collectors = [];
      Sobel(imgData, function(value, x, y) {
        if (value > 40) {
          collectors.push([x, y]);
        }
      });

//          添加一些随机点
      for (var i = 0; i < 300; i++) {
        particles.push([Math.random() * canvas.width, Math.random() * canvas.height]);
      }

//          添加随机边缘点，数量为边缘点数量除于50
      var length = ~~(collectors.length / jxdvalue), random;
      for (var l = 0; l < length; l++) {
        random = (Math.random() * collectors.length) << 0;
        particles.push(collectors[random]);
        collectors.splice(random, 1);
      }

//          添加四顶点坐标
      particles.push([0, 0], [0, canvas.height], [canvas.width, 0], [canvas.width, canvas.height]);

//          使用delaunay三角化获取三角坐标
      var triangles = Delaunay.triangulate(particles);

      var x1, x2, x3, y1, y2, y3, cx, cy;
      for (var i = 0; i < triangles.length; i += 3) {
        x1 = particles[triangles[i]][0];
        x2 = particles[triangles[i + 1]][0];
        x3 = particles[triangles[i + 2]][0];
        y1 = particles[triangles[i]][1];
        y2 = particles[triangles[i + 1]][1];
        y3 = particles[triangles[i + 2]][1];

//              获取三角形中心点坐标
        cx = ~~((x1 + x2 + x3) / 3);
        cy = ~~((y1 + y2 + y3) / 3);

//              获取中心点坐标的颜色值
        var index = (cy * imgData.width + cx) * 4;
        var color_r = imgData.data[index];
        var color_g = imgData.data[index + 1];
        var color_b = imgData.data[index + 2];

//              绘制三角形
        ctx.save();
        ctx.beginPath();
        ctx.moveTo(x1, y1);
        ctx.lineTo(x2, y2);
        ctx.lineTo(x3, y3);
        ctx.closePath();
        ctx.fillStyle = "rgba(" + color_r + "," + color_g + "," + color_b + ",1)";
        ctx.fill();
        ctx.restore();
      }

      box.className = "";
    }, 50);
  }
</script>
</body>
</html>